package ophiux.wechatpay.sdk.client;

import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ophiux.wechatpay.sdk.OphiuxWeChatPaySDKException;
import ophiux.wechatpay.sdk.common.net.HttpsApiRequest;
import ophiux.wechatpay.sdk.common.net.INetApiRequest;
import ophiux.wechatpay.sdk.common.parse.IOphiuxApiParser;
import ophiux.wechatpay.sdk.common.parse.json.OphiuxApiJsonParser;
import ophiux.wechatpay.sdk.common.parse.table.OphiuxApiTableParser;
import ophiux.wechatpay.sdk.common.parse.xml.OphiuxApiXmlParser;
import ophiux.wechatpay.sdk.common.proxy.NetApiRequestProxy;
import ophiux.wechatpay.sdk.common.utils.StringUtil;
import ophiux.wechatpay.sdk.request.OphiuxBaseRequest;
import ophiux.wechatpay.sdk.response.OphiuxResponse;
import ophiux.wechatpay.sdk.util.SignUtils;
import ophiux.wechatpay.sdk.util.WXPayUtil;
import ophiux.wechatpay.sdk.util.XMLFormat;

public class DefaultWechatPayClient implements IWechatPayClient {
	private static Logger logger = LoggerFactory.getLogger(DefaultWechatPayClient.class);
	
	/** 公众账号ID	appid	是	String(32)	wxd678efh567hg6787	微信支付分配的公众账号ID（企业号corpid即为此appId） */
	private String app_id;
	/** 子公众号ID */
	private String sub_appid;
	/** 公众号密钥 */
	private String app_secret;	
	/** 商户号	mch_id	是	String(32)	1230000109	微信支付分配的商户号 */
	private String mch_id;
	/** * 子商户号 */
	private String sub_mch_id;
	/** 公众号签名回调密钥       		微信商户平台-账户设置-安全设置-api安全   */
	private String api_token;
	/** 签名类型	sign_type	否	String(32)	MD5	签名类型，默认为MD5，支持HMAC-SHA256和MD5。 */
	private String sign_type;
	/** 请求地址          Y  */
	private String serviceURL;
	
	/** 返回格式    默认XML*/
	private String format="XML";
	/** 证书路径  */
	private String sslFilePath;
	
 
	/**
	 * 普通商户
	 * @param app_id  		公众账号ID
	 * @param mch_id 		商户号
	 * @param api_token		公众号签名回调密钥
	 * @param sign_type		签名类型
	 * @param serviceURL	请求地址
	 * @param sslFilePath	证书路径 (不需要证书则不传，否则会出错)
	 */
	public DefaultWechatPayClient(String app_id,
			String mch_id, String api_token, String sign_type, String serviceURL,String sslFilePath) {
		this.app_id = app_id;
		this.mch_id = mch_id;
		this.api_token = api_token;
		this.sign_type = sign_type;
		this.serviceURL = serviceURL;
		this.sslFilePath=sslFilePath;
	}

	/**
	 * 服务商商户
	 * @param app_id  		公众账号ID
	 * @param mch_id 		商户号
	 * @param api_token		公众号签名回调密钥
	 * @param sign_type		签名类型
	 * @param serviceURL	请求地址
	 * @param sslFilePath	证书路径 (不需要证书则不传，否则会出错)
	 * @param sub_appid		子公众号ID
	 * @param sub_mch_id	子商户号
	 */
	public DefaultWechatPayClient(String app_id,String mch_id,String api_token,String sign_type, String serviceURL,
			String sslFilePath,String sub_appid,String sub_mch_id) {
		this(app_id,mch_id,api_token,sign_type,serviceURL,sslFilePath);
		this.sub_appid  = sub_appid;
		this.sub_mch_id = sub_mch_id;
	}


	public DefaultWechatPayClient(){
		
	}
	
	@Override
	public <T extends OphiuxResponse> T executor(OphiuxBaseRequest<T> _request)
			throws OphiuxWeChatPaySDKException {
		IOphiuxApiParser<T> parser = null;
		Class clzz = _request.getResponseClass();
		if(format.equals("XML")){
			parser = new OphiuxApiXmlParser<T>(clzz);
		}else if(format.equals("TABLE")){
			parser = new OphiuxApiTableParser<T>(clzz);
		}else if(format.equals("JSON")){
			parser = new OphiuxApiJsonParser<T>(clzz);
		}
		T responseEntity = doSoapApiRequest(_request, parser);
		return responseEntity;
	}
	
	
	public <T extends OphiuxResponse> T doSoapApiRequest(OphiuxBaseRequest<T> _request,IOphiuxApiParser<T> parser) 
											    throws OphiuxWeChatPaySDKException{
		//拼接请求参数
		String httpSoapParam = getHttpSoapParam(_request);
//		System.out.println("微信请求参数："+httpSoapParam);
		logger.info("微信请求参数："+httpSoapParam);
		INetApiRequest netApiRequest = new HttpsApiRequest();
		NetApiRequestProxy netApiReqProxy = new NetApiRequestProxy(netApiRequest);
		String response=null;
		//发送请求
		if(StringUtil.isEmpty(sslFilePath)){
			response = netApiReqProxy.request(serviceURL,_request.getApiMethod(), httpSoapParam,30000);
		}else{
			response = netApiReqProxy.getPostMethodSSL(serviceURL, _request.getApiMethod(), httpSoapParam, sslFilePath, mch_id);
		}
		
		/*WXPay util=new WXPay(app_id,sign_type,mch_id,api_token);
		try {
			 Map<String, String> dd =util.processResponseXml(response);
		} catch (Exception e) {
			e.printStackTrace();
		}*/
		
		
		try {
//			logger.info("微信返回参数：\n"+new String(XMLFormat.outPut(response), "UTF-8"));
			System.out.println("微信返回参数：\n"+new String(XMLFormat.outPut(response), "UTF-8"));
		} catch (Exception e) {
			e.printStackTrace();
		}
		T responseEntity = parser.parser(response);
		responseEntity.setRealResponseDataSource(response);
		responseEntity.setRequestParam(httpSoapParam);
		return responseEntity;
	}
	
	public String getHttpSoapParam(OphiuxBaseRequest _request){
		//拼接  公有参数   map
		Map<String,String> publicParams=new HashMap<String, String>();
		publicParams.put("appid", app_id);
		publicParams.put("sub_appid", sub_appid);
		publicParams.put("app_secret", app_secret);
		publicParams.put("mch_id", mch_id);
		publicParams.put("sub_mch_id", sub_mch_id);
//		publicParams.put("api_token", api_token);
		publicParams.put("sign_type", sign_type);
		
		Map requ=new HashMap();
		requ.putAll(publicParams);
		//获取业务参数
		Map bParamXML = _request.getTextParam();
		if(StringUtil.isEmpty(_request.getTextParam().get("nonce_str")+"")){
			bParamXML.put("nonce_str", WXPayUtil.getNonceStr());
		}
		requ.putAll(bParamXML);
		
		try {
			String sign=SignUtils.getSign(requ, api_token);
			publicParams.put("sign", sign);
		} catch (Exception e) {
			System.out.println("签名发生错误");
			e.printStackTrace();
		}
		
		//将业务参数、共有参数转化为XML格式
		String requestParamXML = _request.toRequestParam(publicParams, bParamXML);
		
		return requestParamXML;
	}

	@Override
	public <T extends OphiuxResponse> String executor_str(
			OphiuxBaseRequest<T> _request) throws OphiuxWeChatPaySDKException {
		IOphiuxApiParser<T> parser = null;
		Class clzz = _request.getResponseClass();
		parser = new OphiuxApiXmlParser<T>(clzz);

		String httpSoapParam = getHttpSoapParam(_request);
//		System.out.println("微信请求参数："+httpSoapParam);
		logger.info("微信请求参数："+httpSoapParam);
		INetApiRequest netApiRequest = new HttpsApiRequest();
		NetApiRequestProxy netApiReqProxy = new NetApiRequestProxy(netApiRequest);
		//发送请求
		String response = netApiReqProxy.request(serviceURL,_request.getApiMethod(), httpSoapParam);
//		System.out.println("微信返回参数："+XMLFormat.outPut(response));
		logger.info("微信返回参数："+XMLFormat.outPut(response));
		String responseEntity = response;
		
		return responseEntity;
	}


	public void setFormat(String format) {
		this.format = format;
	}
	
}
